﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using EL = Microsoft.Practices.EnterpriseLibrary.Security.Cryptography;

namespace CDSBDemandControlService
{
    /// <summary>
    /// Representa serviços básicos de criptografia simétrica.
    /// </summary>
    public sealed class SymmetricCryptographer : IDisposable
    {
        /// <summary>
        /// Algoritmos de criptografia simétrica.
        /// </summary>
        public enum Algorithm
        {
            /// <summary>
            /// Algoritmo DES de criptografia.
            /// </summary>
            DES,
            /// <summary>
            /// Algoritmo RC2 de criptografia.
            /// </summary>
            RC2,
            /// <summary>
            /// Algoritmo Rijndael de criptografia.
            /// </summary>
            Rijndael,
            /// <summary>
            /// Algoritmo Triple DES de criptografia.
            /// </summary>
            TripleDES
        }

        static Dictionary<Algorithm, Type> _algorithms = new Dictionary<Algorithm, Type>();

        EL.SymmetricCryptographer _cryptographer;

        static SymmetricCryptographer()
        {
            _algorithms[Algorithm.DES] = typeof(DESCryptoServiceProvider);
            _algorithms[Algorithm.RC2] = typeof(RC2CryptoServiceProvider);
            _algorithms[Algorithm.Rijndael] = typeof(RijndaelManaged);
            _algorithms[Algorithm.TripleDES] = typeof(TripleDESCryptoServiceProvider);
        }

        /// <summary>
        /// Cria uma nova instância da classe CriptografoSimetrico.
        /// </summary>
        /// <param name="algorithm">O algoritmo de criptografia simétrico.</param>
        /// <param name="key">A chave de criptografia.</param>
        public SymmetricCryptographer(Algorithm algorithm, ProtectedKey key)
        {
            _cryptographer = new EL.SymmetricCryptographer(_algorithms[algorithm], key.Key);
        }

        /// <summary>
        /// Criptografa um texto.
        /// </summary>
        /// <param name="plaintext">O texto a ser criptografado.</param>
        /// <returns>O texto criptografado.</returns>
        public byte[] Encrypt(byte[] plaintext)
        {
            return _cryptographer.Encrypt(plaintext);
        }

        /// <summary>
        /// Descriptografa um texto.
        /// </summary>
        /// <param name="encryptedText">O texto a ser descriptografado.</param>
        /// <returns>O texto descriptografado.</returns>
        public byte[] Decrypt(byte[] encryptedText)
        {
            return _cryptographer.Decrypt(encryptedText);
        }

        /// <summary>
        /// Gera uma chave de criptografia aleatória.
        /// </summary>
        /// <param name="algorithm">O nome do algoritmo de criptografia simétrica que
        /// essa chave vai ser utilizada.</param>
        /// <returns>A chave de criptografia aleatória.</returns>
        public static byte[] GenerateKey(Algorithm algorithm)
        {
            EL.SymmetricKeyGenerator gerador = new Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.SymmetricKeyGenerator();
            return gerador.GenerateKey(_algorithms[algorithm]);
        }

        #region IDisposable Members

        /// <summary>
        /// Libera todos os recursos utilizados por essa instância.
        /// </summary>
        public void Dispose()
        {
            _cryptographer.Dispose();
        }

        #endregion
    }
}
